SQLServer アーキテクチャ ディスクIO操作
SQL Serverのファイルは大きく2つ存在する
1. データファイル
データを実際に格納するファイル。主要なファイル拡張子は.mdfと.ndf。
基本的にはプライマリと呼ばれる1つのファイル(.mdf)だけで十分。
ただ、セカンダリと呼ばれる.ndfも使うことで、データを複数ファイルに分散させることもできる。
ex)よくやるのは別ファイルにして、さらに各ファイルを別ディスクに配置することでIOを分散させるやり方。
2. ログファイル
拡張子は.ldfで、トランザクションログファイルと呼ばれる。
名前の通り、データベースに対する変更をシーケンシャルに書き込んでいくファイル。
SQL Serverでも、実際にデータ変更される前にトランザクションログが更新される仕組みになってる。
ページ
DBでよく出てくるページはSQL Serverでも同じ意味で登場する。
データファイルが作られた際、その中身は8KBのページ区画で分けられる。
SQL Serverはデータを呼び出す際、レコード単位とかではなく、ページ単位で呼び出す。
SQL Serverがやる特徴的なIO操作
先行読み取り(Read Ahead)
SQL Serverでは、クエリによって必要なデータがディスクからバッファキャッシュに読み出される際に、将来的に必要になるかもなデータも一緒に読み出される。
これを先行読み取りと言う。
先行読み取りのページ数には制限があり、エディションによって異なるので注意。
ex)SEなら128ページ、EEなら1024ページ
チェックポイント(checkpoint)
基本的にどのデータベースでもそうだと思うが、コミットされたからといってデータがすぐにファイルに反映されるわけではない。
トランザクションログにも既に書き込み済み、バッファキャッシュでもデータ更新されてるが、データファイルにはまだ反映されてないと言うのは現代のRDBMSのお馴染みの動作である。
このようなデータのことをダーディページと呼ぶ。実際には、データはページ単位で管理されてるのでこう言う呼び方に。 そして、ダーティページを定期的にデータファイルに反映する仕組みをチェックポイントと呼び、そのプロセスをチェックポイントプロセスと呼ぶ。
「SQL Serverは一度のチェックポイントで最大16ページを反映させる」とのこと。
集中書き込み(Eager Write)
データベースに一括で大量書き込みを行うための操作がSQL Serverにはある。こいつは大量書き込みを1つのトランザクションログにしてくれて、ログ書き込みのボトルネックを最小限に抑えてくれる。
ただ、大量書き込みを行うと、その分の大量のダーティページが発生する。
そいつをチェックポイントでちまちま反映するのはたいへん。
てことで集中書き込みという操作で、ダーティページを一斉反映させれる。
レイジー書き込み(Lazy Write)
前提として、SQL Serverのバッファキャッシュは一定量の空きページを用意しておく必要がある。
なぜそんなことをするのか?
ページをディスクからバッファキャッシュに移す際、空いてる箇所を毎回探すのは流石に非効率だから。
フリーリストのように「空いてる所はここだよ!」て都度示してくれてると効率的。
フリーリストを一定量以上確保するためのルール。
フリーリストの確保量が一定を下回ると、閾値を超えるまで以下の作業が実施される。
1. 使用頻度の低いページは空にする。
2. ダーティページがあれば、ディスクに反映する(= レイジー書き込み)
ここで行われるレイジー書き込みを実施してる内部機能を「レイジーライタ」という。
ライトスルー
SQL Serverは、バッファキャッシュからデータをディスクに反映させる際、ディスクにデータが書き込まれるのを待つ仕様になってる。
基本、SQL Serverとは関係なく、OSやディスクコントローラーは個別にキャッシュを持っており、ディスクに書き込む前にそのキャッシュに書き込んで、処理を済まそうとする。これをライトバックと呼ぶ。 言ってしまえば、SQL Serverが一旦バッファキャッシュにページを保持するのもライトバック。
ライトバックしてくれた方が、SQL Server的にもIO処理を待たずに済むからいいのでは?と思ったりするが...。
以下の状況を考えるとナンセンスである。
1. SQL Serverがチェックポイントを実施する
2. OSはSQL Serverからディスク書き込み要求をされるが、一旦独自のキャッシュに保持して後でディスク書き込みしようとする
3. SQL Serverはページがディスクに書き込まれたと思い込み、バッファキャッシュのダーティページを更新
4. ここでサーバーに障害が起きてダウンし、メモリデータが全て飛ぶ
5. 再起動後に以下の問題が起きる
バッファキャッシュ的にはディスク書き込みしたと思ってたデータが、実際にはディスクに書き込まれていない...
こういう不整合が起きないように、SQL Serverはディスクにちゃんと書き込まれるまで待つというスタンスをとる。
ちなみに、SQL Serverはこの機能を実現するためのオプションとして、CreateFile関数に以下のフラグを立ててる。
FILE_FLAG_WRITETHROUGH、FILE_FLAG_NO_BUFFERING
この2つのフラグを立てて、CreateFile関数を実行し、データファイルとログファイルを作成してる。